﻿
using Microsoft.Extensions.Logging;
using System.Text;
using System.Text.Json;

namespace Framework.HttpRequestService
{
    /// <summary>
    /// HTTP请求帮助服务工厂
    /// </summary>
    public class HttpHelpServiceFactory : IHttpHelpService
    {
        /// <summary>
        /// Http请求工厂
        /// </summary>
        private readonly IHttpClientFactory clientFactory;

        /// <summary>
        /// Http请求
        /// </summary>
        private readonly HttpClient httpClient;

        /// <summary>
        /// 注入Http请求工厂
        /// </summary>
        public HttpHelpServiceFactory(IHttpClientFactory httpClientFactory)
        {
            clientFactory = httpClientFactory;
            httpClient = CreateHttpClient();
        }
        
        /// <summary>
        /// 创建HttpClient
        /// </summary>
        /// <returns></returns>
        private HttpClient CreateHttpClient()
        {
            return clientFactory.CreateClient();
        }

        private void SetHttpRequestInfo(string url,string address,object data,Dictionary<string,object> headers = null)
        {
            if (url == null || url.Length <= 0) throw new HttpRequestException("API请求失败：接口地址不能为空。");
            if(url.EndsWith('/'))
            {
                url = url[..^1];
            }
            if (address != null && address.Length > 0 && !address.StartsWith('/'))
            {
                address = $"/{address}";
            }
            httpClient.BaseAddress = new Uri($"{url}{address}");
            if (headers != null)
            {
                foreach (var item in headers)
                {
                    httpClient.DefaultRequestHeaders.TryAddWithoutValidation(item.Key, JsonSerializer.Serialize(item.Value));
                }
            }
        }

        private async Task<T> RequestData<T>(Func<Task<HttpResponseMessage>> func)
        {
            try
            {
                var data = await func();
                data.EnsureSuccessStatusCode();
                var dataStr = await data.Content.ReadAsStringAsync();
                return JsonSerializer.Deserialize<T>(dataStr);
            }
            catch (HttpRequestException ex)
            {
                // 处理HTTP请求异常
                throw new ApplicationException("HTTP请求失败", ex);
            }
            catch(JsonException ex)
            {
                // 处理JSON反序列化异常
                throw new JsonException("响应数据解析失败", ex);
            }
            catch (Exception ex)
            {
                // 处理其他异常
                throw new Exception("请求处理过程中发生错误", ex);
            }
        }

        public string HttpGet(string url, string address, object data, Dictionary<string, object> headers = null)
        {
            SetHttpRequestInfo(url, address, data, headers);
            return RequestData<string>(() => httpClient.GetAsync(httpClient.BaseAddress)).GetAwaiter().GetResult();
        }

        public Task<string> HttpGetAsync(string url, string address, object data, Dictionary<string, object> headers = null)
        {
            SetHttpRequestInfo(url, address, data, headers);
            return RequestData<string>(() => httpClient.GetAsync(httpClient.BaseAddress));
        }

        public T HttpGetConvert<T>(string url, string address, object data, Dictionary<string, object> headers = null)
        {
            SetHttpRequestInfo(url, address, data, headers);
            return RequestData<T>(() => httpClient.GetAsync(httpClient.BaseAddress)).GetAwaiter().GetResult();
        }

        public Task<T> HttpGetConvertAsync<T>(string url, string address, object data, Dictionary<string, object> headers = null)
        {
            SetHttpRequestInfo(url, address, data, headers);
            return RequestData<T>(() => httpClient.GetAsync(httpClient.BaseAddress));
        }

        public string HttpPost(string url, string address, object data, Dictionary<string, object> headers = null)
        {
            SetHttpRequestInfo(url, address, data, headers);
            return RequestData<string>(() => httpClient.PostAsync(httpClient.BaseAddress, new StringContent(JsonSerializer.Serialize(data), Encoding.UTF8))).GetAwaiter().GetResult();
        }

        public Task<string> HttpPostAsync(string url, string address, object data, Dictionary<string, object> headers = null)
        {
            SetHttpRequestInfo(url, address, data, headers);
            return RequestData<string>(() => httpClient.PostAsync(httpClient.BaseAddress, new StringContent(JsonSerializer.Serialize(data), Encoding.UTF8)));
        }

        public T HttpPostConvert<T>(string url, string address, object data, Dictionary<string, object> headers = null)
        {
            SetHttpRequestInfo(url, address, data, headers);
            return RequestData<T>(() => httpClient.PostAsync(httpClient.BaseAddress, new StringContent(JsonSerializer.Serialize(data), Encoding.UTF8))).GetAwaiter().GetResult();
        }

        public Task<T> HttpPostConvertAsync<T>(string url, string address, object data, Dictionary<string, object> headers = null)
        {
            SetHttpRequestInfo(url, address, data, headers);
            return RequestData<T>(() => httpClient.PostAsync(httpClient.BaseAddress, new StringContent(JsonSerializer.Serialize(data), Encoding.UTF8)));
        }

        public Task<T> HttpPost<T>(Action<HttpClient> action, object data)
        {
            action(httpClient);
            return RequestData<T>(() => httpClient.PostAsync(httpClient.BaseAddress, new StringContent(JsonSerializer.Serialize(data), Encoding.UTF8)));
        }

        public Task<T> HttpPost<T>(Func<HttpClient,Task<HttpResponseMessage>> action, object data)
        {
            try
            {
                var requestData = action(httpClient);
                return RequestData<T>(() => { return requestData; });
            }
            catch (Exception ex)
            {
                throw new Exception("请求处理过程中发生错误", ex);
            }
        }

        public Task<T> HttpPost<T>(Func<HttpClient,Task<T>> func)
        {
            try
            {
                return func(httpClient);
            }
            catch (Exception ex)
            {
                throw new Exception("请求处理过程中发生错误", ex);
            }
        }
    }

    /// <summary>
    /// HTTP请求帮助服务工厂
    /// </summary>
    public class HttpHelpService
    {
        private readonly IHttpClientFactory _clientFactory;
        private readonly ILogger<HttpHelpServiceFactory> _logger;
        private readonly JsonSerializerOptions _jsonOptions;

        public HttpHelpService(IHttpClientFactory httpClientFactory,ILogger<HttpHelpServiceFactory> logger = null)
        {
            _clientFactory = httpClientFactory;
            _logger = logger;
            _jsonOptions = new JsonSerializerOptions
            {
                PropertyNameCaseInsensitive = true,
                WriteIndented = false
            };
        }

        private HttpClient CreateHttpClient()
        {
            return _clientFactory.CreateClient();
        }

        private void ConfigureRequest(HttpClient client, string url, string address, Dictionary<string, object> headers = null)
        {
            if (string.IsNullOrWhiteSpace(url)) throw new ArgumentException("API请求失败：接口地址不能为空。");

            url = url.TrimEnd('/');
            address = address?.TrimStart('/');

            client.BaseAddress = new Uri($"{url}/{address}");

            if (headers != null)
            {
                foreach (var header in headers)
                {
                    client.DefaultRequestHeaders.TryAddWithoutValidation(header.Key,header.Value?.ToString());
                }
            }
        }

        private async Task<T> RequestDataAsync<T>(Func<Task<HttpResponseMessage>> requestFunc)
        {
            using var client = CreateHttpClient();

            try
            {
                var response = await requestFunc();
                response.EnsureSuccessStatusCode();

                var content = await response.Content.ReadAsStringAsync();
                _logger?.LogDebug("Received response: {Content}", content);

                return JsonSerializer.Deserialize<T>(content, _jsonOptions) ?? throw new JsonException("反序列化结果为null");
            }
            catch (HttpRequestException ex)
            {
                _logger?.LogError(ex, "HTTP请求失败");
                throw new ApplicationException($"HTTP请求失败: {ex.StatusCode}", ex);
            }
            catch (JsonException ex)
            {
                _logger?.LogError(ex, "响应数据解析失败");
                throw new JsonException("响应数据解析失败", ex);
            }
            catch (Exception ex)
            {
                _logger?.LogError(ex, "请求处理过程中发生错误");
                throw new ApplicationException("请求处理过程中发生错误", ex);
            }
        }

        public async Task<string> GetAsync(string url, string address, Dictionary<string, object> queryParams = null,Dictionary<string, object> headers = null)
        {
            using var client = CreateHttpClient();
            ConfigureRequest(client, url, address, headers);

            var queryString = queryParams != null? "?" + string.Join("&", queryParams.Select(kvp => $"{kvp.Key}={Uri.EscapeDataString(kvp.Value?.ToString() ?? "")}")) : "";

            return await RequestDataAsync<string>(() =>client.GetAsync(client.BaseAddress + queryString));
        }

        public async Task<T> GetAsync<T>(string url, string address, Dictionary<string, object> queryParams = null,  Dictionary<string, object> headers = null)
        {
            using var client = CreateHttpClient();
            ConfigureRequest(client, url, address, headers);

            var queryString = queryParams != null
                ? "?" + string.Join("&", queryParams.Select(kvp => $"{kvp.Key}={Uri.EscapeDataString(kvp.Value?.ToString() ?? "")}"))
                : "";

            return await RequestDataAsync<T>(() =>
                client.GetAsync(client.BaseAddress + queryString));
        }

        public async Task<string> PostAsync(string url, string address, object data,  Dictionary<string, object> headers = null)
        {
            using var client = CreateHttpClient();
            ConfigureRequest(client, url, address, headers);

            var content = new StringContent( JsonSerializer.Serialize(data, _jsonOptions), Encoding.UTF8, "application/json");

            return await RequestDataAsync<string>(() => client.PostAsync(client.BaseAddress, content));
        }

        public async Task<T> PostAsync<T>(string url, string address,  object data, Dictionary<string, object> headers = null)
        {
            using var client = CreateHttpClient();
            ConfigureRequest(client, url, address, headers);

            var content = new StringContent( JsonSerializer.Serialize(data, _jsonOptions), Encoding.UTF8, "application/json");

            return await RequestDataAsync<T>(() => client.PostAsync(client.BaseAddress, content));
        }

        public async Task<T> SendAsync<T>(Func<HttpClient, Task<HttpResponseMessage>> requestFactory)
        {
            using var client = CreateHttpClient();
            return await RequestDataAsync<T>(() => requestFactory(client));
        }
    }
}
